
package com.be.beadmin.product.impl;

import cn.hutool.core.date.DateUtil;
import com.be.beadmin.basicData.dto.output.UserEx;
import com.be.beadmin.basicData.dto.output.UserNameId;
import com.be.beadmin.basicData.service.UserService;
import com.be.beadmin.common.entity.PageEntity;
import cn.hutool.core.util.ObjectUtil;
import com.be.beadmin.common.exception.BeadminException;
import com.be.beadmin.common.utils.JpaQueryBuilder;
import com.be.beadmin.common.utils.JpaSortBuilder;
import com.be.beadmin.product.dto.output.ActualTaskWorkHour;
import com.be.beadmin.product.entity.WorkingHoursCount;
import com.be.beadmin.product.entity.WorkingHoursCount_;
import lombok.RequiredArgsConstructor;
import com.be.beadmin.product.mapper.WorkingHoursCountMapperEx;
import com.be.beadmin.product.repository.WorkingHoursCountRepository;
import com.be.beadmin.product.service.WorkingHoursCountService;
import com.be.beadmin.product.dto.input.WorkingHoursCountDto;
import com.be.beadmin.product.dto.output.WorkingHoursCountEx;
import com.be.beadmin.product.dto.input.WorkingHoursCountQueryCriteria;
import com.be.beadmin.product.mapper.WorkingHoursCountMapper;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.Pageable;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Pageable;
import org.springframework.stereotype.Service;

import javax.persistence.criteria.Predicate;
import javax.persistence.criteria.Order;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.*;

/**
* @description 服务实现
* @author zjm
* @date 2023-12-08
**/
@Service
@RequiredArgsConstructor
public class WorkingHoursCountServiceImpl implements WorkingHoursCountService {

    @Autowired
    private  WorkingHoursCountRepository workingHoursCountRepository;
    @Autowired
    private  WorkingHoursCountMapper workingHoursCountMapper;
    @Autowired
    private  WorkingHoursCountMapperEx workingHoursCountExMapper;


    @Autowired
    private UserService userService;
    @Override
    public Page<WorkingHoursCountEx> getWorkingHoursCountByPage(PageEntity pageEntity) {
            Pageable pageable = PageRequest.of(
            pageEntity.getCurrent() -1,
            pageEntity.getPageSize());
            Page<WorkingHoursCount> page = workingHoursCountRepository.findAll((root, criteriaQuery, criteriaBuilder) -> {
                    List<Predicate> list = new ArrayList<>();
                    Predicate pre1 =   JpaQueryBuilder.getPredicate(root, pageEntity.getFilters(), criteriaBuilder);
                    list.add(pre1);
                    Predicate pre2 = criteriaBuilder.equal(root.get(WorkingHoursCount_.delete), 0); //过滤为0
                    list.add(pre2);
                    Predicate[] p = new Predicate[list.size()];
                    List<Order> orders = new ArrayList<>();
                    if(pageEntity.getSorters() != null && pageEntity.getSorters().size() > 0) {
                        orders = JpaSortBuilder.getPredicate(root, pageEntity.getSorters(), criteriaBuilder);
                        criteriaQuery.orderBy(orders);
                    } else {
                        criteriaQuery.orderBy(criteriaBuilder.desc(root.get(WorkingHoursCount_.createTime).as(Date.class)));
                    }
                    return  criteriaBuilder.and(list.toArray(p));
                    }
                    , pageable);
            Page<WorkingHoursCountEx> page1 = page.map(workingHoursCountExMapper::toEntity);
            return page1;
    }

    @Override
    public void addWorkingHoursCount(WorkingHoursCountDto workingHoursCountDto) {
            WorkingHoursCount result = workingHoursCountRepository.findWorkingHoursCountByIdAndDelete(workingHoursCountDto.getId(), 0);
            if(ObjectUtil.isNotEmpty(result)) {
                throw new BeadminException("WorkingHoursCount不存在,请重新查询");
            }
            WorkingHoursCount workingHoursCount = workingHoursCountMapper.toEntity(workingHoursCountDto);
            workingHoursCountRepository.save(workingHoursCount);
    }

    /**
     * 生成工时统计
     *
     */
    @Override
    public void generateWorkingHoursCount() {
        // 先删除之前的数据
        delWorkingHoursCount();
        // 生成这个人的各种工时统计报表
        /**
         * 【实际任务工时】：来源于工序的操作时间
         * 【实际项目填报工时】：来源于815
         * 【实际工单填报工时】：来源于工时补录，见备注1
         * 目前有一张数据表，分别有如下字段：
         * name 用户名
         * process_id 工序名
         * manufact_start_date 工序开始时间
         * manufact_end_date 工序结束时间
         * sum_work_hours 用户当前工序的累计工时
         *
         * 现需要用sql统计某个用户指定月份（比如2023-10）的工时
         * 1. 如果工序没有结束时间， 结束时间为当前时间now(),
         * 2. 如果工序开始时间与结束时间在同一个月份，只需要统计到该月，工时为sum_work_hours；
         * 3. 如果工序开始和结束时间跨越不同月份的情况下进行每个月的工时统计，需要对跨越的月份进行拆分并计算，每个月的工时都为：按照每个月中有效天数占当月的天数（月底-manufact_start_date） / 开始到结束总天数（manufact_end_date-manufact_start_date） * 累计工时（工时为sum_work_hours）；
         */
        List<String> allMonths = workingHoursCountRepository.findAllMonth();
        System.out.println(String.join(",",allMonths));
//        ActualTaskWorkHour actualTaskWorkHour = workingHoursCountRepository.sumPersonnelIdWorkingHours();
        // 找到所有用户
        List<UserNameId> allUserNameAndId = userService.getAllUserNameAndId();

        List<WorkingHoursCount> list = new ArrayList<>();
        // 每个月的结果
        for (String allMonth: allMonths) { // 每个年月份

            SimpleDateFormat inputDateFormat = new SimpleDateFormat("yyyyMM");
            // 定义输出日期格式
            SimpleDateFormat outputDateFormat = new SimpleDateFormat("yyyyMM");


            Date monthDate;
            String outputDateStr;

            try {
                monthDate = inputDateFormat.parse(allMonth);
                outputDateStr = outputDateFormat.format(monthDate);
            } catch (ParseException e) {
                throw new RuntimeException(e);
            }
            // 每个用户的结果
            // 只能每个用户单独计算一次了
            for (UserNameId userNameId : allUserNameAndId) {
                Map<String, Double> stringDoubleMap = workingHoursCountRepository.statWorkHourByUserAndMonth(outputDateStr, outputDateStr+"01", userNameId.getUserName());
                WorkingHoursCount workingHoursCount = new WorkingHoursCount();
                workingHoursCount.setDate(monthDate);
                workingHoursCount.setPersonnelName(userNameId.getUserName());
                workingHoursCount.setActualTaskWorkhour(stringDoubleMap.get("manufact_wh"));
                workingHoursCount.setActualProjectWorkhour(stringDoubleMap.get("project_wh"));
                workingHoursCount.setActualWoWorkhour(stringDoubleMap.get("workorder_wh"));
                if (workingHoursCount.getActualWoWorkhour() == null && workingHoursCount.getActualTaskWorkhour() == null && workingHoursCount.getActualProjectWorkhour() == null)  {
                    continue;
                }
                list.add(workingHoursCount);
            }
            workingHoursCountRepository.saveAll(list);
//            for (Map<String,Double > map : workingHoursCountRepository.statWorkHourAllUserByMonth(allMonth, allMonth+"01")) {
//                for (Map.Entry<String, Double> entry : map.entrySet()) {
//                    System.out.println("Key: " + entry.getKey() + ", Value: " + entry.getValue());
//                }
//                WorkingHoursCount workingHoursCount = new WorkingHoursCount();
//                workingHoursCount.setDate(monthDate);
//                workingHoursCount.setPersonnelName(String.valueOf(map.get("user_name")));
//                workingHoursCount.setActualTaskWorkhour(map.get("manufact_wh"));
//                workingHoursCount.setActualProjectWorkhour(map.get("project_wh"));
//                workingHoursCount.setActualWoWorkhour(map.get("workorder_wh"));
//                workingHoursCountRepository.save(workingHoursCount);
//            }
        }



//        ActualTaskWorkHour actualTaskWorkHour = workingHoursCountRepository.sumPersonnelIdWorkingHours();
        // 实际项目填报工时 统计， 存到同一条记录中
        // 实际工单填报工时 统计， 也存到同一条记录中。



    }

    @Override
    public void updateWorkingHoursCount(WorkingHoursCountDto workingHoursCountDto) {
            WorkingHoursCount workingHoursCount = workingHoursCountRepository.findWorkingHoursCountById(workingHoursCountDto.getId());
            workingHoursCount = workingHoursCountMapper.toEntity(workingHoursCountDto);
            workingHoursCountRepository.save(workingHoursCount);
    }


    @Override
    public void delWorkingHoursCount(String id) {
        WorkingHoursCount workingHoursCount = workingHoursCountRepository.findWorkingHoursCountById(id);
        workingHoursCount.setDelete(1);
        workingHoursCountRepository.save(workingHoursCount);
    }

    /**
     *
     */
    @Override
    public void delWorkingHoursCount() {
        workingHoursCountRepository.deleteAll();
    }

    @Override
    public void delWorkingHoursCounts (List<String> ids) { }
}